"""
工作流执行上下文

提供工作流执行期间的数据共享和状态管理。
"""

from typing import Dict, Any, Optional, List
from datetime import datetime
import logging
import threading
from copy import deepcopy


class WorkflowContext:
    """
    工作流执行上下文
    
    在工作流执行期间提供数据共享、状态管理和服务访问。
    """
    
    def __init__(self,
                 workflow_id: str = None,
                 initial_data: Dict[str, Any] = None,
                 config: Dict[str, Any] = None):
        self.workflow_id = workflow_id
        self.config = config or {}
        
        # 数据存储
        self._data: Dict[str, Any] = initial_data or {}
        self._metadata: Dict[str, Any] = {}
        
        # 执行状态
        self.start_time = datetime.utcnow()
        self.current_node_id: Optional[str] = None
        self.execution_history: List[Dict[str, Any]] = []
        
        # 线程安全
        self._lock = threading.RLock()
        
        # 日志
        self.logger = logging.getLogger(f"workflow.context.{workflow_id}")
        
        # 服务引用（可以通过依赖注入设置）
        self.services: Dict[str, Any] = {}
        
        # 错误处理
        self.errors: List[Dict[str, Any]] = []
        self.warnings: List[Dict[str, Any]] = []
    
    def set_data(self, key: str, value: Any) -> None:
        """设置数据"""
        with self._lock:
            self._data[key] = value
            self.logger.debug(f"设置数据: {key}")
    
    def get_data(self, key: str, default: Any = None) -> Any:
        """获取数据"""
        with self._lock:
            return self._data.get(key, default)
    
    def update_data(self, data: Dict[str, Any]) -> None:
        """批量更新数据"""
        with self._lock:
            self._data.update(data)
            self.logger.debug(f"批量更新数据: {list(data.keys())}")
    
    def has_data(self, key: str) -> bool:
        """检查是否存在数据"""
        with self._lock:
            return key in self._data
    
    def remove_data(self, key: str) -> Any:
        """移除数据"""
        with self._lock:
            return self._data.pop(key, None)
    
    def get_all_data(self) -> Dict[str, Any]:
        """获取所有数据的副本"""
        with self._lock:
            return deepcopy(self._data)
    
    def clear_data(self) -> None:
        """清空所有数据"""
        with self._lock:
            self._data.clear()
            self.logger.debug("清空所有数据")
    
    def set_metadata(self, key: str, value: Any) -> None:
        """设置元数据"""
        with self._lock:
            self._metadata[key] = value
    
    def get_metadata(self, key: str, default: Any = None) -> Any:
        """获取元数据"""
        with self._lock:
            return self._metadata.get(key, default)
    
    def set_current_node(self, node_id: str) -> None:
        """设置当前执行的节点"""
        with self._lock:
            self.current_node_id = node_id
            self.logger.debug(f"当前节点: {node_id}")
    
    def add_execution_record(self, node_id: str, node_name: str, 
                           status: str, duration: float = None,
                           error: str = None, data: Dict[str, Any] = None) -> None:
        """添加执行记录"""
        with self._lock:
            record = {
                'node_id': node_id,
                'node_name': node_name,
                'status': status,
                'timestamp': datetime.utcnow().isoformat(),
                'duration': duration,
                'error': error,
                'data_keys': list(data.keys()) if data else []
            }
            self.execution_history.append(record)
            self.logger.debug(f"添加执行记录: {node_name} - {status}")
    
    def add_error(self, node_id: str, error_message: str, 
                  error_type: str = "execution_error") -> None:
        """添加错误"""
        with self._lock:
            error_record = {
                'node_id': node_id,
                'error_type': error_type,
                'error_message': error_message,
                'timestamp': datetime.utcnow().isoformat()
            }
            self.errors.append(error_record)
            self.logger.error(f"节点错误 {node_id}: {error_message}")
    
    def add_warning(self, node_id: str, warning_message: str,
                   warning_type: str = "execution_warning") -> None:
        """添加警告"""
        with self._lock:
            warning_record = {
                'node_id': node_id,
                'warning_type': warning_type,
                'warning_message': warning_message,
                'timestamp': datetime.utcnow().isoformat()
            }
            self.warnings.append(warning_record)
            self.logger.warning(f"节点警告 {node_id}: {warning_message}")
    
    def set_service(self, name: str, service: Any) -> None:
        """设置服务引用"""
        with self._lock:
            self.services[name] = service
            self.logger.debug(f"设置服务: {name}")
    
    def get_service(self, name: str) -> Any:
        """获取服务引用"""
        with self._lock:
            return self.services.get(name)
    
    def has_service(self, name: str) -> bool:
        """检查是否存在服务"""
        with self._lock:
            return name in self.services
    
    def get_config(self, key: str, default: Any = None) -> Any:
        """获取配置值"""
        return self.config.get(key, default)
    
    def set_config(self, key: str, value: Any) -> None:
        """设置配置值"""
        self.config[key] = value
    
    @property
    def execution_duration(self) -> float:
        """执行时长（秒）"""
        return (datetime.utcnow() - self.start_time).total_seconds()
    
    @property
    def has_errors(self) -> bool:
        """是否有错误"""
        return len(self.errors) > 0
    
    @property
    def has_warnings(self) -> bool:
        """是否有警告"""
        return len(self.warnings) > 0
    
    def get_execution_summary(self) -> Dict[str, Any]:
        """获取执行摘要"""
        with self._lock:
            completed_nodes = len([r for r in self.execution_history if r['status'] == 'completed'])
            failed_nodes = len([r for r in self.execution_history if r['status'] == 'failed'])
            
            return {
                'workflow_id': self.workflow_id,
                'start_time': self.start_time.isoformat(),
                'execution_duration': self.execution_duration,
                'current_node': self.current_node_id,
                'total_nodes_executed': len(self.execution_history),
                'completed_nodes': completed_nodes,
                'failed_nodes': failed_nodes,
                'error_count': len(self.errors),
                'warning_count': len(self.warnings),
                'data_keys': list(self._data.keys()),
                'metadata_keys': list(self._metadata.keys())
            }
    
    def get_node_execution_history(self, node_id: str) -> List[Dict[str, Any]]:
        """获取特定节点的执行历史"""
        with self._lock:
            return [r for r in self.execution_history if r['node_id'] == node_id]
    
    def get_errors_by_node(self, node_id: str) -> List[Dict[str, Any]]:
        """获取特定节点的错误"""
        with self._lock:
            return [e for e in self.errors if e['node_id'] == node_id]
    
    def get_warnings_by_node(self, node_id: str) -> List[Dict[str, Any]]:
        """获取特定节点的警告"""
        with self._lock:
            return [w for w in self.warnings if w['node_id'] == node_id]
    
    def create_child_context(self, child_workflow_id: str) -> 'WorkflowContext':
        """创建子上下文"""
        child_context = WorkflowContext(
            workflow_id=child_workflow_id,
            initial_data=self.get_all_data(),
            config=self.config.copy()
        )
        
        # 复制服务引用
        child_context.services = self.services.copy()
        
        return child_context
    
    def merge_child_context(self, child_context: 'WorkflowContext') -> None:
        """合并子上下文的结果"""
        with self._lock:
            # 合并数据
            self._data.update(child_context.get_all_data())
            
            # 合并执行历史
            self.execution_history.extend(child_context.execution_history)
            
            # 合并错误和警告
            self.errors.extend(child_context.errors)
            self.warnings.extend(child_context.warnings)
            
            self.logger.debug(f"合并子上下文: {child_context.workflow_id}")
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        with self._lock:
            return {
                'workflow_id': self.workflow_id,
                'start_time': self.start_time.isoformat(),
                'execution_duration': self.execution_duration,
                'current_node_id': self.current_node_id,
                'data': self._data.copy(),
                'metadata': self._metadata.copy(),
                'config': self.config.copy(),
                'execution_history': self.execution_history.copy(),
                'errors': self.errors.copy(),
                'warnings': self.warnings.copy(),
                'execution_summary': self.get_execution_summary()
            }
    
    def __str__(self) -> str:
        """字符串表示"""
        summary = self.get_execution_summary()
        return (f"WorkflowContext(id={self.workflow_id}, "
                f"duration={summary['execution_duration']:.2f}s, "
                f"nodes={summary['total_nodes_executed']}, "
                f"errors={summary['error_count']})")
    
    def __repr__(self) -> str:
        """详细字符串表示"""
        return self.__str__()
